package net.chrisrichardson.ec2deployer.cluster

import net.chrisrichardson.ec2deployer.core.AWSProperties
import groovy.mock.interceptor.MockFor
import net.chrisrichardson.ec2deployer.core.EC2Server
import net.chrisrichardson.ec2deployer.core.EC2
import net.chrisrichardson.ec2deployer.core.EC2InstanceType

class SingleInstanceTopologyTest extends GroovyTestCase {
    MockFor mockEc2
    AWSProperties awsProperties
    def clusterSpec

    public void setUp() {
        mockEc2 = new MockFor(EC2.class)
        def props = new Properties()
        awsProperties = new AWSProperties(props)
    }

    public void testAllocateServers_noSlaves() {

        clusterSpec = new ClusterSpec().tomcats(1).slaves(0)

        def allocatedServers = []

        mockEc2.demand.newServers {numberOfServers, instanceType, extraParams ->
            assertEquals 1, numberOfServers
            assertEquals EC2InstanceType.SMALL, instanceType
            assertEquals([:], extraParams)
            def servers = (1..numberOfServers).collect {new EC2Server()}
            allocatedServers.addAll(servers)
            servers
        }


        mockEc2.demand.newServers {numberOfServers, instanceType ->
            assertEquals 0, numberOfServers
            []
        }

        mockEc2.use {
            def ec2 = new EC2(awsProperties)

            def topology = new SingleInstanceTopology()

            ClusterHosts servers = topology.allocateServers(ec2, clusterSpec, false)

            assertEquals allocatedServers[0], servers.databaseServer
            assertEquals ([], servers.mySqlSlaves)
            assertEquals allocatedServers[0..0], servers.tomcats
            assertEquals allocatedServers[0], servers.apacheServer
            assertEquals allocatedServers[0], servers.jmeter

        }
    }

    public void testAllocateServers_oneSlaves() {

        clusterSpec = new ClusterSpec().tomcats(1).slaves(1)

        def allocatedServers = []

        mockEc2.demand.newServers {numberOfServers, instanceType, extraParams ->
            assertEquals 1, numberOfServers
            assertEquals EC2InstanceType.SMALL, instanceType
            assertEquals([:], extraParams)
            def servers = (1..numberOfServers).collect {new EC2Server()}
            allocatedServers.addAll(servers)
            servers
        }

        mockEc2.demand.newServers {numberOfServers, instanceType ->
            assertEquals 1, numberOfServers
            assertEquals EC2InstanceType.SMALL, instanceType
            def servers = (1..numberOfServers).collect {new EC2Server()}
            allocatedServers.addAll(servers)
            servers
        }

         mockEc2.use {
            def ec2 = new EC2(awsProperties)

            def topology = new SingleInstanceTopology()

            ClusterHosts servers = topology.allocateServers(ec2, clusterSpec, false)

            assertEquals allocatedServers[0], servers.databaseServer
            assertEquals allocatedServers[1..1], servers.mySqlSlaves
            assertEquals allocatedServers[0..0], servers.tomcats
            assertEquals allocatedServers[0], servers.apacheServer
            assertEquals allocatedServers[0], servers.jmeter

        }
    }

    void testSingleInstanceClusterWithHASlave() {
        ClusterSpec clusterSpec = new ClusterSpec().tomcats(1).instanceType(EC2InstanceType.SMALL).slaves(1).webApp("fooWar", "ptrack")
                .catalinaOptsBuilder({builder, databasePrivateDnsName, slaveNames ->}).schema("ptrack", ["ptrack": "ptrack"], ["src/test/resources/testdml1.sql", "src/test/resources/testdml2.sql"])
        clusterSpec.topology(SingleInstanceTopology.simpleName)
        clusterSpec.haSlave()

        def allocatedServers = []

        mockEc2.demand.newServers {numberOfServers, instanceType, extraParams ->
            assertEquals 1, numberOfServers
            assertEquals EC2InstanceType.SMALL, instanceType
            assertEquals([:], extraParams)
            def servers = (1..numberOfServers).collect {new EC2Server()}
            allocatedServers.addAll(servers)
            servers
        }

        mockEc2.demand.newServersElsewhere {numberOfServers, instanceType, otherServer, params ->
            // assertEquals 1, numberOfServers
            assertEquals EC2InstanceType.SMALL, instanceType
            assertEquals 1, numberOfServers
            assertEquals allocatedServers[0], otherServer
            assertEquals ([:], params)
            def servers = (1..numberOfServers).collect {new EC2Server()}
            allocatedServers.addAll(servers)
            servers
        }

        mockEc2.demand.newServers {numberOfServers, instanceType ->
            assertEquals 0, numberOfServers
            assertEquals EC2InstanceType.SMALL, instanceType
            []
        }

        mockEc2.use {
           def ec2 = new EC2(awsProperties)

           def topology = new SingleInstanceTopology()

           ClusterHosts servers = topology.allocateServers(ec2, clusterSpec, false)

           assertEquals allocatedServers[0], servers.databaseServer
           assertEquals allocatedServers[1..1], servers.mySqlSlaves
           assertEquals allocatedServers[0..0], servers.tomcats
           assertEquals allocatedServers[0], servers.apacheServer
           assertEquals allocatedServers[0], servers.jmeter

       }

    }

    public void testAllocateServers_noSlavesWithEbs() {

        clusterSpec = new ClusterSpec().tomcats(1).slaves(0)
        clusterSpec.withExistingEbsVolume("vol-123434", "/dev/sdq")

        def allocatedServers = []

        mockEc2.demand.getAvailabilityZoneOfEbsVolume { "hong-kong" }
        
        mockEc2.demand.newServers {numberOfServers, instanceType, extraParams ->
            assertEquals 1, numberOfServers
            assertEquals EC2InstanceType.SMALL, instanceType
            assertEquals(["Placement.AvailabilityZone" : "hong-kong"], extraParams)
            
            def servers = (1..numberOfServers).collect {new EC2Server()}
            allocatedServers.addAll(servers)
            servers
        }


        mockEc2.demand.newServers {numberOfServers, instanceType ->
            assertEquals 0, numberOfServers
            []
        }

        mockEc2.use {
            def ec2 = new EC2(awsProperties)

            def topology = new SingleInstanceTopology()

            ClusterHosts servers = topology.allocateServers(ec2, clusterSpec, false)

            assertEquals allocatedServers[0], servers.databaseServer
            assertEquals ([], servers.mySqlSlaves)
            assertEquals allocatedServers[0..0], servers.tomcats
            assertEquals allocatedServers[0], servers.apacheServer
            assertEquals allocatedServers[0], servers.jmeter

        }
    }

}